package graphicView;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.JPanel;

import model.AnchorPoint;
import model.ClassImpl;
import model.RelationshipImpl;

import java.util.Observable;
import java.util.Observer;
import java.util.Vector;

public class MyPanel extends JPanel implements ActionListener, Observer {

	private Vector<ClassGraphicObject> classToDisplay;
	private Vector<RelationshipGraphicObject> relationshipToDisplay;
	private ActiveClassNotifier activeClassNotifier;
	private Boolean relationshipIsActive;
	private RelationshipImpl theActiveRelationship;
	int srcOrDest;

	public MyPanel(Vector<ClassGraphicObject> classToDisplay,
			Vector<RelationshipGraphicObject> relationshipToDisplayIn,
			ActiveClassNotifier activeClassNotifierIn) {
		this.classToDisplay = classToDisplay;
		activeClassNotifier = activeClassNotifierIn;
		relationshipIsActive = false;

		final Vector<ClassGraphicObject> classForListeners = this.classToDisplay;

		relationshipToDisplay = relationshipToDisplayIn;
		final Vector<RelationshipGraphicObject> relationshipForListeners = this.relationshipToDisplay;

		setBorder(BorderFactory.createLineBorder(Color.black));

		addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				boolean clickedOnAnchor = false;
				RelationshipGraphicObject rgo;
				for (int i = relationshipForListeners.size() - 1; i >= 0; i--) {
					rgo = relationshipForListeners.elementAt(i);
					if ((((e.getX() - rgo.getModel().getDest().x) * (e.getX() - rgo
							.getModel().getDest().x)) + ((e.getY() - rgo
							.getModel().getDest().y) * (e.getY() - rgo
							.getModel().getDest().y))) <= 100) {
						

						activeClassNotifier.aRelationshipEndPointIsActive();
						theActiveRelationship = rgo.getModel();
						srcOrDest = 0;
						clickedOnAnchor = true;
						repaint();
						break;
					} else if ((((e.getX() - relationshipForListeners
							.elementAt(0).getModel().getSrc().x) * (e.getX() - relationshipForListeners
							.elementAt(0).getModel().getSrc().x)) + ((e.getY() - relationshipForListeners
							.elementAt(0).getModel().getSrc().y) * (e.getY() - relationshipForListeners
							.elementAt(0).getModel().getSrc().y))) <= 100) {
						
						activeClassNotifier.aRelationshipEndPointIsActive();
						theActiveRelationship = rgo.getModel();
						srcOrDest = 1;
						clickedOnAnchor = true;
						repaint();
						break;
					}
					if (clickedOnAnchor)
						break;

				}
				if (!clickedOnAnchor) {
					ClassGraphicObject cgo;
					for (int i = classForListeners.size() - 1; i >= 0; i--) {
						cgo = classForListeners.elementAt(i);
						if (e.getX() > cgo.getoX() && e.getY() > cgo.getoY()
								&& e.getX() < cgo.getoX() + cgo.getWidth()
								&& e.getY() < cgo.getoY() + cgo.getHeight()) {
							cgo.activate();
							activeClassNotifier.changeClass(cgo.getModel());
							classForListeners.remove(cgo);
							classForListeners.add(cgo);
							break;
							// moveSquare(e.getX(), e.getY());
						}
					}
				}
			}
		});

		addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				for (ClassGraphicObject cgo : classForListeners) {
					if (e.getX() > cgo.getoX() && e.getY() > cgo.getoY()
							&& e.getX() < cgo.getoX() + cgo.getWidth()
							&& e.getY() < cgo.getoY() + cgo.getHeight()) {
						activeClassNotifier.changeClass(cgo.getModel());
						System.out.println("BLAMO");
						classForListeners.remove(cgo);
						classForListeners.add(cgo);
						repaint();
						invalidate();
						break;
					}
				}
			}
		});

		addMouseListener(new MouseAdapter() {
			public void mouseReleased(MouseEvent e) {

				if (relationshipIsActive) {
					for (ClassGraphicObject cgo : classForListeners) {
						for (AnchorPoint ap : cgo.getModel().getAnchorPoints()) {
							if ((((e.getX() - ap.x) * (e.getX() - ap.x)) + ((e.getY() - ap.y) * (e.getY() - ap.y))) <= 100) {
								if (srcOrDest == 0) {
									theActiveRelationship.setDest(ap);
								} else if (srcOrDest == 1) {
									theActiveRelationship.setSrc(ap);
								}
								activeClassNotifier.deactivateRelationship();
								break;
							}

						}
						if (!relationshipIsActive)
							break;
					}
				} else {
					for (ClassGraphicObject cgo : classForListeners) {

						cgo.deactivate();
						
					}
				}
				repaint();
				activeClassNotifier.deactivateRelationship();

			}
		});

		addMouseMotionListener(new MouseAdapter() {
			public void mouseDragged(MouseEvent e) {
				for (ClassGraphicObject cgo : classForListeners) {
					if (cgo.isActive()) {
						// System.out.println("derp");
						moveClass(
								e.getX()/*- (e.getX() - classForListeners.getoX())*/,
								e.getY()/*
										 * - (e.getY()
										 * -classForListeners.getoY())
										 */, cgo);
					}
				}
			}
		});

	}

	/*
	 * public void mousePressed(MouseEvent e){ //moveSquare(e.getX(),e.getY());
	 * }
	 * 
	 * @Override public void mouseDragged(MouseEvent e){ //if (e.getX() >
	 * classToDisplay.getoX() && e.getY() > classToDisplay.getoY());
	 * moveSquare(e.getX(),e.getY()); }
	 */
	private void moveClass(int x, int y, ClassGraphicObject classToMove) {

		// Current square state, stored as final variables
		// to avoid repeat invocations of the same methods.
		final int CURR_X = classToMove.getoX();
		final int CURR_Y = classToMove.getoY();

		if ((CURR_X != x) || (CURR_Y != y)) {

			// The square is moving, repaint background
			// over the old square location.
			// repaint(CURR_X, CURR_Y, CURR_W + OFFSET, CURR_H + OFFSET);

			// Update coordinates.
			classToMove.setoX(x);
			classToMove.setoY(y);
			classToMove.getModel().updateAnchors();

			// Repaint the square at the new location.
			// repaint(classToDisplay.getoX(), classToDisplay.getoY(),
			// classToDisplay.getWidth() + OFFSET,
			// classToDisplay.getHeight() + OFFSET);
			repaint();
			invalidate();

		}
	}

	public Dimension getPreferredSize() {
		return new Dimension(1024, 768);
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		// g.drawString("This is my custom Panel!", 10, 20);
		for (ClassGraphicObject cgo : classToDisplay) {

			cgo.drawClass(g, relationshipIsActive);
		}

		for (RelationshipGraphicObject rgo : relationshipToDisplay) {
			rgo.drawRelationship(g);
		}
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void update(Observable obj, Object arg) {
		if (arg instanceof Boolean) {
			// System.out.println("!!!!!!!!!!!!!!!!!!!!");
			this.relationshipIsActive = (Boolean) arg;
		}

	}
	
	
	

}